package com.jason.java.lib.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * @description: MyClientSocket
 * @author: ChenBaoYang
 * @createDate: 2022/3/18 11:32 上午
 */
public class MyClientSocket {

    private static Socket socket;
    public static boolean connection_state = false;
    private static OutputStreamWriter osw;

    //线程工厂
    private static ThreadFactory threadFactory = new ThreadFactory() {
        private final AtomicInteger integer = new AtomicInteger();

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "ThreadPool thread:" + integer.getAndIncrement());
        }
    };

    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,
            new ArrayBlockingQueue<Runnable>(5),threadFactory);

    public static void main(String[] args) {

        while(!connection_state){
            connect();
            try{
                Thread.sleep(3000);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

//        try {
//            // 创建客户端Socket，指定服务器地址和端口
//            Socket socket = new Socket("127.0.0.1", 8881);
//            // 获取输出流，向服务器端发送信息
//            OutputStream os = socket.getOutputStream();
//            // 创建PrintWriter
//            PrintWriter pw = new PrintWriter(os);
//            // 获取客户端的ip地址
//            InetAddress inetAddress = InetAddress.getLocalHost();
//            String ip = inetAddress.getHostAddress();
//            // 输出内容
//            pw.write("客户端：~" + ip + "~ 接入服务器！！");
//            pw.flush();
//            pw.close();
//            socket.shutdownOutput();
//            socket.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }

    public static void connect(){
        try{
            socket = new Socket("192.168.18.208",12345);
            connection_state = true;
            OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream(),"UTF-8");
            executor.execute(new ClientListener(socket));
            executor.execute(new ClientSend(socket,osw));
            executor.execute(new ClientHeart(socket,osw));
        }catch (Exception e){
            e.printStackTrace();
            connection_state = false;
        }
    }

    //自动重连机制
    public static void reconnect(){
        while(!connection_state){
            System.out.println("正在尝试重新连接.....");
            connect();
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class ClientListener implements Runnable{

        public Socket socket;

        public ClientListener(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try{
                InputStream is = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is,"UTF-8");
                //专程BufferReader
                BufferedReader reader = new BufferedReader(isr);
                //获取数据转成字符串
                String info = null;
                while ((info = reader.readLine()) != null) {
                    //循环读取客户端的信息
                    System.out.println("客户端发送过来的信息:" + info);
                }
                //关闭输入流
                socket.shutdownInput();

            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    static class ClientSend implements Runnable{

        public Socket socket;
        private OutputStreamWriter osw;
        public ClientSend(Socket socket, OutputStreamWriter osw) {
            this.socket = socket;
            this.osw = osw;
        }

        @Override
        public void run() {
            try{
                OutputStream os = socket.getOutputStream();
                PrintWriter pw = new PrintWriter(os);
                // 获取客户端的ip地址
                InetAddress inetAddress = InetAddress.getLocalHost();
                String ip = inetAddress.getHostAddress();
                while(true){
                    Thread.sleep(1000L);
                    // 输出内容
                    pw.write("客户端：~" + ip + "~ 接入服务器！！");
                    pw.flush();
                    pw.close();
                }
            }catch (Exception e){
                e.printStackTrace();
                try{
                    socket.close();
                    MyClientSocket.connection_state = false;
                    MyClientSocket.reconnect();

                }catch (Exception e2){
                    e2.printStackTrace();
                }
            }
        }
    }

    static class ClientHeart implements Runnable {

        private Socket socket;
        private OutputStreamWriter osw;
        public ClientHeart(Socket socket,OutputStreamWriter osw){
            this.socket = socket;
            this.osw = osw;
        }

        @Override
        public void run() {
            try{
                System.out.println("心跳包线程已启动");

                while(true){
                    Thread.sleep(5000);
                    osw.write("*****心跳包*****");
                    osw.flush();
                }
            }catch (Exception e){
                e.printStackTrace();
                try{
                    socket.close();
                    MyClientSocket.connection_state = false;
                    MyClientSocket.reconnect();

                }catch (Exception e2){
                    e2.printStackTrace();
                }
            }
        }
    }
}
